#include "lc_deep_inspect_op_Operator.h"
#include "UDP6_Packet.hh"
#include "TCP6_Packet.hh"

#define BUF_SIZE 1024

void
deep_inspect_op::my_install(void * data)
{
}

void * 
deep_inspect_op::my_get()
{
  return NULL;
}

void
deep_inspect_op::my_purge(void * data)
{
}

void 
deep_inspect_op::my_init()
{

}

pktTypes::Packet *
deep_inspect_op::gendata_inRequest()
{
  pktTypes::Packet * pkt = new pktTypes::Packet(new char[BUF_SIZE], BUF_SIZE);
  pktTypes::Eth_Packet eth6(*pkt);
  pktTypes::IP6_Packet ip6(eth6);
  pktTypes::TCP6_Packet tcp6(ip6);
  
  // transfer ip values
  
  ip6.setIPVersion();
  ip6.setPayloadLength(100);
  ip6.setNextHeader(IPPROTO_TCP);
  ip6.setHopLimit(255);
  
  // get source/dest addresses from flow state
  
  in6_addr src;
  uint32_t src_core = (0xa << 24) | (0x1 << 16) | (0x1 << 8) | 0xb;
  src.s6_addr32[0] = src_core;
  src.s6_addr32[1] = 0;
  src.s6_addr32[2] = 0;
  src.s6_addr32[3] = 0;
  in6_addr dst;
  uint32_t dst_core = (0xa << 24) | (0x1 << 16) | (0x1 << 8) | 0x3;
  dst.s6_addr32[0] = dst_core;
  dst.s6_addr32[1] = 0;
  dst.s6_addr32[2] = 0;
  dst.s6_addr32[3] = 0;

  ip6.setSourceAddress(src);
  ip6.setDestinationAddress(dst);
  
  // transfer tcp values
  tcp6.setSrcPort(htons(6000));
  tcp6.setDstPort(htons(5000));
  tcp6.setSeqNum(htonl(1000));
  tcp6.setAckSeqNum(htonl(1000));
  tcp6.setDataOff(0);
  tcp6.setFin(false);
  tcp6.setSyn(false);
  tcp6.setRst(false);
  tcp6.setPsh(false);
  tcp6.setAck(false);
  tcp6.setUrg(false);
  tcp6.setWindow(0);
  tcp6.setUrgPtr(0);
  tcp6.chksum();

//   // set upd values
//   udp6.setSrcPort(6000);
//   udp6.setDstPort(5000);
//   udp6.setUDPLength(100);
//   udp6.chksum();

  lagniappe::FlowID fid = getFlowID(pkt);
  InspectRecord_p ir(new InspectRecord(getNewMutex()));
  ir->init();
  flowMapping[fid] = ir;
  
  return pkt;

}

void
deep_inspect_op::handleMyPort(pktTypes::Packet * data, unsigned long dataSize)
{
  assert(data != NULL);
  
  // transform data into a TCP packet
  
  pktTypes::Eth_Packet eth6(*data);
  pktTypes::IP6_Packet ip6(eth6);
  pktTypes::TCP6_Packet tcp6(ip6);

  uint16_t totalLength = ip6.getPayloadLength();
  totalLength -= pktTypes::TCP6_HSIZE;

  pktTypes::payload_t start = tcp6.getPayload();

  // get flow id

  lagniappe::FlowID fid = getFlowID(data);

  // look up flow state, create if necessary

  InspectRecord_p ir(flowMapping[fid]);

  if(!ir) {
    InspectRecord_p irt(new InspectRecord(getNewMutex()));
    ir = irt;
    ir->init();
  }

  if(totalLength > 1) {
  // do deep inspection of packet payload
  char tempC[totalLength + 1];
  memcpy(tempC, start, totalLength - 1);
  tempC[totalLength] = '\0';

  for(int i = 0; i < totalLength; i = i + 4) {
    std::string temp(tempC);
    
    if(temp.find("BAD") != std::string::npos) {
      ir->reportInfraction("BAD");
    }
    if(temp.find("NAUGHTY") != std::string::npos) {
      ir->reportInfraction("NAUGHTY");
    }
    if(temp.find("CREDITCARD") != std::string::npos) {
      ir->reportInfraction("CREDITCARD");
    }
    if(temp.find("TRADESECRET") != std::string::npos) {
      ir->reportInfraction("TRADESECRET");
    }

    }

  }
  if(ir->blockable()) {
    if(!inProf) {
      delete data->getPayload();
      delete data;
    }
  }
  else {
    data_out(data, dataSize);
  }
  
  return;

}
